﻿using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindowsService1
{
    public class MqttDataService
    {
        public static readonly MqttTopicLogger _mqttTopicLogger = MqttTopicLogger.Instance;

        public static string BU_id;
        public static string District_id;
        public static string Factory_id;
        public static string Production_line_id;
        public static string Device_name;
        public static string Topic;
        public static string Work_Center_id;
        public class OperationData
        {
            public int Item_Value { get; set; }
            public string Start_Time { get; set; }
            public string End_Time { get; set; }
        }


        public class MqttMessage
        {
            public string bu_id { get; set; }
            public string district_id { get; set; }
            public string factory_id { get; set; }
            public string production_line_id { get; set; }
            public string production_processes_id { get; set; }
            public string work_center_id { get; set; }
            public string station_id { get; set; }
            public string device_name { get; set; }
            public List<TagList> taglist { get; set; }
        }

        public class TagList
        {
            public string device_time { get; set; }
            public Dictionary<string, OperationData> collection_items { get; set; }

            public Dictionary<string, float> collection2_items { get; set; }
        }



        public class YuCeMqttMessage
        {
            public string bu_id { get; set; }
            public string district_id { get; set; }
            public string factory_id { get; set; }
            public string production_line_id { get; set; }
            public string production_processes_id { get; set; }
            public string work_center_id { get; set; }
            public string station_id { get; set; }
            public string device_name { get; set; }
            public List<TagLists> taglist { get; set; }
        }

        public class TagLists
        {
            public string device_time { get; set; }

            public Dictionary<string, float> collection_items { get; set; }
        }



        /// <summary>
        /// 创建MQTT消息（向后兼容版本）
        /// </summary>
        /// <param name="source">数据源</param>
        /// <param name="type">采集类型</param>
        /// <param name="processedValues">处理后的数据值</param>
        /// <param name="_plcAddresses">PLC地址映射</param>
        /// <param name="_collectionGroups">采集组配置</param>
        /// <returns></returns>
        public static string CreateMqttMessage(string source, AcquisitionType type, List<StationData> processedValues, 
            Dictionary<AcquisitionType, Dictionary<string, string>> _plcAddresses, 
            Dictionary<AcquisitionType, CollectionGroupConfig> _collectionGroups)
        {
            return CreateMqttMessage(source, type, processedValues, _plcAddresses, _collectionGroups, null);
        }

        /// <summary>
        /// 创建MQTT消息（配置驱动版本）
        /// </summary>
        /// <param name="source">数据源</param>
        /// <param name="type">采集类型</param>
        /// <param name="processedValues">处理后的数据值</param>
        /// <param name="_plcAddresses">PLC地址映射</param>
        /// <param name="_collectionGroups">采集组配置</param>
        /// <param name="typeConfig">采集类型配置（用于配置驱动）</param>
        /// <returns></returns>
        public static string CreateMqttMessage(string source, AcquisitionType type, List<StationData> processedValues, 
            Dictionary<AcquisitionType, Dictionary<string, string>> _plcAddresses, 
            Dictionary<AcquisitionType, CollectionGroupConfig> _collectionGroups,
            AcquisitionTypeConfig typeConfig)
        {
            try
            {
                _mqttTopicLogger.WriteSystemInfo($"开始创建 MQTT 消息, 类型: {type}, 数据点数量: {processedValues?.Count ?? 0}");

                if (processedValues == null || processedValues.Count == 0)
                {
                    _mqttTopicLogger.WriteSystemInfo("没有需要处理的数据，返回 null");
                    return null;
                }
                string messageJson = "";
                var addresses = _plcAddresses[type];
                var config = _collectionGroups[type];
                var collectionItems = new Dictionary<string, OperationData>();
                var YuCeicollectionItems = new Dictionary<string, float>();

                // 获取当前时间作为设备时间
                var currentTime = DateTime.Now;
                var deviceTimeStr = currentTime.ToString("yyyy-MM-dd HH:mm:ss.fff");
               
                _mqttTopicLogger.WriteSystemInfo($"处理数据类型: {type}, 当前时间: {deviceTimeStr}");

                // 使用配置驱动的方式确定处理类型
                string processType = DetermineProcessType(type, typeConfig);
                _mqttTopicLogger.WriteSystemInfo($"确定的处理类型: {processType}");

                switch (processType.ToUpper())
                {
                    case "PPM":
                        ProcessPPMData(processedValues, addresses, config, collectionItems);   //有变化就上传
                        var message = new MqttMessage
                        {
                            bu_id = BU_id,
                            district_id = District_id,
                            factory_id = Factory_id,
                            production_line_id = Production_line_id,
                            production_processes_id = string.Empty,
                            work_center_id = Work_Center_id,
                            station_id = "1",
                            device_name = Device_name,
                            taglist = new List<TagList>
                            {
                            new TagList
                            {
                                device_time = deviceTimeStr,
                                collection_items = collectionItems
                            }
                            }
                        };
                        messageJson = JsonConvert.SerializeObject(message, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None });
                        break;
                        
                    case "FLOAT":
                    case "PARAMETER":
                        ProcessFloatData(processedValues, addresses, config, YuCeicollectionItems);  //不需要考虑变化
                        var message2 = new YuCeMqttMessage
                        {
                            bu_id = BU_id,
                            district_id = District_id,
                            factory_id = Factory_id,
                            production_line_id = Production_line_id,
                            production_processes_id = string.Empty,
                            work_center_id = Work_Center_id,
                            station_id = "1",
                            device_name = Device_name,
                            taglist = new List<TagLists>
                            {
                                new TagLists
                                {
                                    device_time = deviceTimeStr,//GetMicroTimestamp(),
                                    collection_items = YuCeicollectionItems
                                }
                            }
                        };
                         messageJson = JsonConvert.SerializeObject(message2, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None });
                        break;
                        
                    case "ROBOT":
                        // 机械臂类型的数据不在这里处理MQTT消息，直接返回null
                        _mqttTopicLogger.WriteSystemInfo($"机械臂类型 {type} 的消息将通过专用通道发送");
                        return null;
                        
                    default:
                        _mqttTopicLogger.WriteSystemError($"未知的处理类型: {processType} (采集类型: {type})");
                        return null;
                }

                if (collectionItems.Count == 0&&YuCeicollectionItems.Count==0)
                {
                    _mqttTopicLogger.WriteSystemInfo("没有有效的采集项，返回 null");
                    return null;
                }

                // 记录创建的消息内容（已移至分类日志系统）

                return messageJson;
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"创建 MQTT 消息时发生错误: {ex.Message}", ex);
                return null;
            }
        }

        /// <summary>
        /// 确定处理类型（完全配置驱动）
        /// </summary>
        /// <param name="type">采集类型</param>
        /// <param name="typeConfig">类型配置</param>
        /// <returns>处理类型</returns>
        private static string DetermineProcessType(AcquisitionType type, AcquisitionTypeConfig typeConfig)
        {
            try
            {
                // 必须使用配置中的ProcessType，不再有任何硬编码逻辑
                if (typeConfig != null && !string.IsNullOrEmpty(typeConfig.ProcessType))
                {
                    _mqttTopicLogger.WriteConfigOperation("处理类型", "使用配置", $"{typeConfig.ProcessType} (采集类型: {type})");
                    return typeConfig.ProcessType;
                }

                // 配置缺失时的错误处理 - 不再提供默认映射，要求完全配置化
                if (typeConfig == null)
                {
                    _mqttTopicLogger.WriteSystemError($"采集类型 {type} 缺少配置信息，无法确定处理类型。请在Config.xml中添加对应的AcquisitionType配置");
                    throw new InvalidOperationException($"采集类型 {type} 未配置，请在Config.xml中添加配置");
                }

                if (string.IsNullOrEmpty(typeConfig.ProcessType))
                {
                    _mqttTopicLogger.WriteSystemError($"采集类型 {type} 的processType属性为空。请在Config.xml中设置processType属性为：PPM、Float 或 Robot");
                    throw new InvalidOperationException($"采集类型 {type} 的processType属性未设置");
                }

                // 这里不应该到达，但为了安全起见
                _mqttTopicLogger.WriteSystemError($"采集类型 {type} 的processType配置异常：'{typeConfig.ProcessType}'");
                throw new InvalidOperationException($"采集类型 {type} 的processType配置无效");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"确定处理类型时出错: {ex.Message}", ex);
                _mqttTopicLogger.WriteConfigOperation("配置检查", "processType属性", $"请确保Config.xml中为采集类型 {type} 正确配置了processType属性");
                throw; // 重新抛出异常，不提供默认值
            }
        }

        /// <summary>
        /// PPM点位数据
        /// </summary>
        /// <param name="processedValues"></param>
        /// <param name="addresses"></param>
        /// <param name="config"></param>
        /// <param name="collectionItems"></param>
        // 添加静态字段来存储上次发送的数据
        private static Dictionary<string, OperationData> _lastSentData = new Dictionary<string, OperationData>();

        public static void ProcessPPMData(List<StationData> processedValues, Dictionary<string, string> addresses, CollectionGroupConfig config, Dictionary<string, OperationData> collectionItems)
        {
            try
            {
                _mqttTopicLogger.WriteSystemInfo($"开始处理 PPM 数据，数据点数量: {processedValues.Count}");

                // 创建临时字典存储当前所有数据点
                var tempItems = new Dictionary<string, OperationData>();

                foreach (var value in processedValues)
                {
                    int itemValue = 0;
                    DateTime startTime = DateTime.Now;
                    var addressPair = addresses.FirstOrDefault(x => x.Key == value.Name);
                    if (!string.IsNullOrEmpty(addressPair.Key))
                    {
                        if (addressPair.Key == "PPM" || addressPair.Key == "TotalTime")
                        {
                            itemValue = Convert.ToInt32(value.MainValue.ToString());
                            // 计算开始时间 (结束时间 - 时长)
                            startTime = value.Timestamp.AddMinutes(-1); //默认1分钟上传
                        }
                        else
                        {
                            itemValue = Convert.ToInt32(ConvertToIntegerWithThreeDecimals(value.MainValue));
                            // 计算开始时间 (结束时间 - 时长)
                            startTime = value.Timestamp.AddMilliseconds(-itemValue);
                        }

                        var operationData = new OperationData
                        {
                            Item_Value = itemValue,
                            Start_Time = startTime.ToString("yyyy-MM-dd HH:mm:ss.fff"),
                            End_Time = value.Timestamp.ToString("yyyy-MM-dd HH:mm:ss.fff")
                        };

                        // 检查数据是否发生变化
                        bool shouldAdd = true;

                        // 检查是否与上次发送的数据重复
                        if (_lastSentData.TryGetValue(addressPair.Key, out var lastData))
                        {
                            var currentEndTime = operationData.End_Time.ToString();
                            var lastEndTime = lastData.End_Time.ToString();

                            if (string.Equals(lastEndTime, currentEndTime, StringComparison.OrdinalIgnoreCase))
                            {
                                shouldAdd = false;
                                _mqttTopicLogger.WriteSystemInfo($"跳过重复数据点: {addressPair.Key}");
                                continue;
                            }
                        }

                        if (shouldAdd)
                        {
                            tempItems[addressPair.Key] = operationData;
                            _mqttTopicLogger.WriteSystemInfo($"处理数据点: {addressPair.Key}, 值: {itemValue}, " +
                                           $"开始时间: {startTime:yyyy-MM-dd HH:mm:ss.fff}, " +
                                           $"结束时间: {operationData.End_Time}");
                        }
                    }
                    else
                    {
                        _mqttTopicLogger.WriteSystemError($"未找到数据点 {value.Name} 对应的地址配置");
                    }
                }

                // 将处理后的数据添加到最终结果并更新上次发送的数据
                foreach (var item in tempItems)
                {
                    collectionItems[item.Key] = item.Value;
                    _lastSentData[item.Key] = item.Value; // 更新上次发送的数据
                }

                _mqttTopicLogger.WriteSystemInfo($"PPM 数据处理完成，处理后的数据点数量: {collectionItems.Count}");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"处理 PPM 数据时出错: {ex.Message}", ex);
                throw;
            }
        }

        /// <summary>
        /// 预测性点位 - 轴参数处理
        /// </summary>
        /// <param name="processedValues">处理后的站点数据</param>
        /// <param name="addresses">地址映射</param>
        /// <param name="config">采集组配置</param>
        /// <param name="endTime">结束时间</param>
        /// <param name="collectionItems">采集项目字典</param>
        // 添加静态字段来存储上次发送的数据
        private static Dictionary<string, float> _lastSentValues = new Dictionary<string, float>();

        public static void ProcessFloatData(List<StationData> processedValues, Dictionary<string, string> addresses, CollectionGroupConfig config, Dictionary<string, float> collectionItems)
        {
            try
            {
                _mqttTopicLogger.WriteSystemInfo($"开始处理状态数据，数据点数量: {processedValues.Count}, 配置组: {config.Name}");

                foreach (var value in processedValues)
                {
                    try
                    {
                        var addressPair = addresses.FirstOrDefault(x => x.Key == value.Name);
                        string key = null;

                        if (!string.IsNullOrEmpty(addressPair.Key))
                        {
                            key = addressPair.Key;
                        }
                        else
                        {
                            string address = $"D{int.Parse(config.StartAddress.Substring(1)) + processedValues.IndexOf(value) * 2}";
                            var addrPair = addresses.FirstOrDefault(x => x.Value == address);
                            if (!string.IsNullOrEmpty(addrPair.Key))
                            {
                                key = addrPair.Key;
                            }
                        }

                        if (key != null)
                        {
                            float itemValue = (float)value.MainValue;


                            //bool shouldAdd = true;


                            //if (_lastSentValues.TryGetValue(key, out var lastValue))
                            //{
                            //    if (lastValue == itemValue)
                            //    {
                            //        shouldAdd = false;
                            //        _mqttTopicLogger.WriteSystemInfo($"跳过重复数据点: {key}, 值未变化: {itemValue}");
                            //        continue;
                            //    }
                            //}

                            //if (shouldAdd)
                            //{
                            collectionItems[key] = itemValue;
                            _lastSentValues[key] = itemValue;
                            _mqttTopicLogger.WriteSystemInfo($"处理数据点: {key}, 值: {itemValue}");
                            //}
                        }
                        else
                        {
                            _mqttTopicLogger.WriteSystemError($"未找到数据点 {value.Name} 对应的配置");
                        }
                    }
                    catch (Exception ex)
                    {
                        _mqttTopicLogger.WriteSystemError($"处理数据点 {value.Name} 时出错: {ex.Message}", ex);
                    }
                }

                _mqttTopicLogger.WriteSystemInfo($"状态数据处理完成，处理后的数据点数量: {collectionItems.Count}");
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"处理状态数据时出错: {ex.Message}", ex);
            }
        }

        private static object ConvertToIntegerWithThreeDecimals(object value)
        {
            try
            {
                if (value == null) return 0;

                if (value is float floatValue)
                {
                    return (int)Math.Round(floatValue * 1000);
                }
                else if (value is double doubleValue)
                {
                    return (int)Math.Round(doubleValue * 1000);
                }
                else if (value is decimal decimalValue)
                {
                    return (int)Math.Round(decimalValue * 1000);
                }
                else
                {
                    // 尝试转换其他类型
                    float converted = Convert.ToSingle(value);
                    return (int)Math.Round(converted * 1000);
                }
            }
            catch (Exception ex)
            {
                _mqttTopicLogger.WriteSystemError($"转换值到整数时出错: {ex.Message}, 值: {value}", ex);
                return 0;
            }
        }

        /// <summary>
        /// 时间变换
        /// </summary>
        /// <returns></returns>
        private static string GetMicroTimestamp()
        {
            var utcNow = DateTime.UtcNow;
            var unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            var totalMicroseconds = (long)((utcNow - unixEpoch).TotalMilliseconds * 1000);
            return totalMicroseconds.ToString();
        }
    }
}
